package main

import (
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"

	_ "github.com/mattn/go-sqlite3"
	"github.com/skip2/go-qrcode"
)

type BillDishDetailStruct struct {
	Num              int
	Bid_disothername string
	Bid_disprice     int
	Bid_x1           int
	Bid_y1           int
	Bid_x2           int
	Bid_y2           int
	Score            int
}

type BillInfoStruct struct {
	Cmd                    string
	Mac                    string
	Bill_totalmoney        float32
	Bill_returnmoney       float32
	Bill_paymoney          float32
	Bill_returnmoneyremark string
	Bill_paytype           int
	Bill_empid             int
	Bill_empname           string
	Bill_remark            string
	Bill_state             int
	Bill_account           string
	Telphone               string
	Bill_imagedate         string
	Dishes                 []BillDishDetailStruct
}

type MealDataPushStruct struct {
	FoodName string
}

type MealDataPushListStruct struct {
	Order_id  string
	Card_id   string
	Meal_time int64
	Meal_data []MealDataPushStruct
}

type BillDetialStruct struct {
	Cmd    string
	BillId string
	Dishes []BillDishDetailStruct
}

type BillQueryInfoStruct struct {
	Bill_paytime  int64
	Bill_paytype  int
	Bill_account  string
	Bill_paymoney int
	Bill_empname  string
	Bill_id       string
	Bill_remark   string
	Telphone      string
}

type BillQueryInfos struct {
	Cmd   string
	Count int
	Datas []BillQueryInfoStruct
}

type UserInfoStruct struct {
	Cmd          string
	Emp_id       uint32
	Emp_name     string
	Emp_pass     string
	Emp_position string
}

type UserNames struct {
	Cmd   string
	Names []string
}

type ChargeInfo struct {
	Bill_id    string
	Intime     uint32
	TotalMoney int
	Telphone   string
}

type ChargeInfos struct {
	Cmd   string
	Datas []ChargeInfo
}

type ReportLog struct {
	Name        string
	Intime      uint32
	Outtime     uint32
	Totalamount int
	Totalmoney  int
}

type ReportLogs struct {
	Cmd   string
	Count int
	Datas []ReportLog
}

//创建数据库
func initRobotdb() {
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()

		sqlCreateTable := `
-- bill_dishes
create table  bill_dishes
/**EZDML_DESC_START**
bill_dishes(账单菜品)
//记录一个账单中的所有菜品信息
--------------------------------------
id(编号)                    PKInteger
bid_billid(账单编号)        FKString
bid_disothername(菜品别名)  String
bid_disprice(价格)          Integer
bid_x1                      Float
bid_y1                      Float
bid_x2                      Float
bid_y2                      Float
score                       Integer
**EZDML_DESC_END**/
(
       id                INTEGER primary key autoincrement not null,
       bid_billid        TEXT references bill_info(bill_id),
       bid_disothername  TEXT,
       bid_disprice      INTEGER,
       bid_x1            NUMERIC,
       bid_y1            NUMERIC,
       bid_x2            NUMERIC,
       bid_y2            NUMERIC,
       score             INTEGER
);

-- bill_info
create table  bill_info
/**EZDML_DESC_START**
bill_info(账单流水)
//记录已生成的账单信息
--------------------------------------------
id(编号)                          PKInteger
bill_id(账单编号)                 String      //机器唯一标识+时间串
bill_empid(员工编号)              Integer     //当前登陆的用户编号
bill_empname(员工姓名)            String      //当前登陆的用户姓名
bill_totalmoney(应收金额)         Integer
bill_paymoney(实收金额)           Integer     //实收为0表示挂账
bill_returnmoney(折扣金额)        Integer
bill_returnmoneyremark(折扣备注)  String      //套餐为 xxx，实际是多少 折扣是多少
bill_paytype(付款方式)            Integer     //0初始化 1一卡通 2虚拟卡 3支付宝 4微信 5现金 6挂账 7其他
bill_paytime(结账时间)            Integer
bill_imagepathname(流水图像名)    String
bill_remark(备注)                 String
bill_state(账单状态)              Integer     //1已删除
bill_account(账户)                String      //一卡通/虚拟卡类账号
bill_upload(是否上传)             Bool
**EZDML_DESC_END**/
(
       id                INTEGER primary key autoincrement not null,
       bill_id           TEXT,
       bill_empid        INTEGER,
       bill_empname      TEXT,
       bill_totalmoney   INTEGER not null,
       bill_paymoney     INTEGER,
       bill_returnmoney  INTEGER,
       bill_returnmoneyremark TEXT,
       bill_paytype      INTEGER,
       bill_paytime      INTEGER not null,
       bill_imagepathname TEXT,
       bill_remark       TEXT,
       bill_state        INTEGER,
       bill_account      TEXT,
       bill_upload       BOOLEAN
);
create unique index IDU_bill_info_bill_id on bill_info(bill_id);

-- credit_info
create table  credit_info
/**EZDML_DESC_START**
credit_info(挂账单)
//存储挂账单
-------------------------------------------
id(编号)                         PKInteger
credit_billid(账单编号)          FKString
credit_telphone(挂账人联系方式)  String
credit_intime(挂账时间)          Integer
credit_outtime(销账时间)         Integer
credit_totalmoney(应收金额)      Integer
credit_exist(销账单是否被删除)   Bool        //0存在 1已删
**EZDML_DESC_END**/
(
       id                INTEGER primary key autoincrement not null,
       credit_billid     TEXT references bill_info(bill_id),
       credit_telphone   TEXT,
       credit_intime     INTEGER,
       credit_outtime    INTEGER,
       credit_totalmoney INTEGER,
       credit_exist      BOOLEAN
);

-- employee_info
create table  employee_info
/**EZDML_DESC_START**
employee_info(员工信息表)
//记录所有员工信息
---------------------------------
emp_id(员工编号)       PKInteger
emp_name(员工姓名)     String
emp_pass(密码)         String
emp_position(职位)     String
emp_status(在职状态)   String      //在/离/休（不能删，仅仅是逻辑删除）
emp_intime(入职时间)   Integer     //入职日期
emp_outtime(离职日期)  Integer     //离职日期
**EZDML_DESC_END**/
(
       emp_id            INTEGER primary key not null,
       emp_name          TEXT,
       emp_pass          TEXT,
       emp_position      TEXT,
       emp_status        TEXT,
       emp_intime        INTEGER,
       emp_outtime       INTEGER
);

-- employee_logs
create table  employee_logs
/**EZDML_DESC_START**
employee_logs(登陆信息表)
//记录系统的登入，登出信息
------------------------------------------
id(编号)                        PKInteger
empid(员工编号)                 Integer
empname(员工姓名)               String
intime(登入时间)                Integer
outtime(登出时间)               Integer
totalamount(总单数)             Integer
totalmoney(总钱数)              Integer
typeplusam(收款类型单数钱数和)  String      //1_amount1_money1,2_amount2_money2.....
**EZDML_DESC_END**/
(
       id                INTEGER primary key not null,
       empid             INTEGER,
       empname           TEXT,
       intime            INTEGER,
       outtime           INTEGER,
       totalamount       INTEGER,
       totalmoney        INTEGER,
       typeplusam        TEXT
);

		`
		if _, err := db.Exec(sqlCreateTable); err != nil {
			fmt.Printf("%q \n", err)
		}
	} else {
		fmt.Printf("initrobotdb error=%q \n", err)
	}
}

//判断是否存在管理员用户，如果不存在则创建
func initRobotdbAdminUser() {
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		nCount := 0
		db.QueryRow("select count(*) from employee_info where emp_name = ?", "admin").Scan(&nCount)
		if nCount <= 0 {
			if tx, err := db.Begin(); err == nil {
				if stmt, err := tx.Prepare("insert into employee_info(emp_name,emp_pass,emp_position) values(?,?,?)"); err == nil {
					defer stmt.Close()
					stmt.Exec("admin", "123456", "管理员")
				} else {
					fmt.Printf("initRobotdbAdminUser error=%q \n", err)
				}

				tx.Commit()
			}
		}
	}
}

/* 用户登录：get url=http://127.0.0.1:10001/user_login?name=admin
{
	Cmd: "user_login",
	EmpId: 0,
	Pwd: "123456",
	Position: "管理员/收银员"
}
*/
func user_login(w http.ResponseWriter, r *http.Request) {
	name := r.FormValue("name")
	//
	reply := make(map[string]interface{})
	//
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		position := ""
		pwd := ""
		empId := 0
		db.QueryRow("select emp_pass, emp_position, emp_id from employee_info where emp_name=?", name).Scan(&pwd, &position, &empId)
		reply["Pwd"] = pwd
		reply["Position"] = position
		reply["EmpId"] = empId
	}
	reply["Cmd"] = "user_login"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 查询所有用户名字信息：get url=http://127.0.0.1:10001/user_queryname
{
	Cmd: "user_queryname",
	Names:["admin","emp1"]
}
*/
func user_queryname(w http.ResponseWriter, r *http.Request) {
	var reply UserNames
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		if rows, err := db.Query("select emp_name from employee_info"); err == nil {
			defer rows.Close()
			for rows.Next() {
				var name string
				if err := rows.Scan(&name); err == nil {
					reply.Names = append(reply.Names, name)
				}
			}
		}
	}
	reply.Cmd = "user_queryname"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 根据用户名查询用户详情 get url=http://127.0.0.1:10001/user_querydetail?name=admin
{
	Cmd: "user_querydetail",
	Emp_id:1212122,
	Emp_name:"admin",
	Emp_pass:"123456",
	Emp_position:"管理员/收银员"
}
*/
func user_querydetail(w http.ResponseWriter, r *http.Request) {
	username := r.FormValue("name")
	var reply UserInfoStruct
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		var id uint32
		var name, pwd, position string
		db.QueryRow("select emp_id,emp_name,emp_pass,emp_position from employee_info where emp_name=?", username).Scan(&id, &name, &pwd, &position)
		reply.Emp_id = id
		reply.Emp_name = name
		reply.Emp_pass = pwd
		reply.Emp_position = position
	}
	reply.Cmd = "user_querydetail"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 删除用户根据用户id, url=http://127.0.0.1:10001/user_delete?id=1
{
	Cmd:"user_delete",
	Result:"Ok"
}
*/
func user_delete(w http.ResponseWriter, r *http.Request) {
	id := r.FormValue("id")
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		db.Exec("delete from employee_info where emp_id=?", id)
	}
	reply := make(map[string]interface{})
	reply["Cmd"] = "user_delete"
	reply["Result"] = "Ok"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 修改用户信息 url=http://127.0.0.1:10001/user_delete
{
	Cmd:"user_edit"
	Emp_id:1,
	Emp_name:"admin",
	Emp_pass:"123456",
	Emp_position:"管理员"
}
{
	Cmd:"user_edit",
}
*/
func user_edit(w http.ResponseWriter, r *http.Request) {
	body, _ := ioutil.ReadAll(r.Body)
	//
	reply := make(map[string]interface{})
	//
	var dat map[string]interface{}
	if err := json.Unmarshal(body, &dat); err == nil {
		if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
			defer db.Close()
			db.Exec("update employee_info set emp_name=?,emp_pass=?,emp_position=? where emp_id=?", dat["Emp_name"], dat["Emp_pass"], dat["Emp_position"], dat["Emp_id"])
		}
	}
	reply["Cmd"] = "user_edit"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 添加用户 url = http://127.0.0.1:10001/user_add
{
	Cmd: "user_add",
	Emp_name: "admin",
	Emp_pass: "123456",
	Emp_position: "管理员/收银员"
}
{
	Cmd: "user_add",
	ErrorCode: 0=成功 1="用户已经存在"
	Emp_name: "admin",
	Emp_pass: "123456",
	Emp_position: "管理员/收银员"
}
*/
func user_add(w http.ResponseWriter, r *http.Request) {
	body, _ := ioutil.ReadAll(r.Body)
	reply := make(map[string]interface{})
	//
	var dat map[string]interface{}
	if err := json.Unmarshal(body, &dat); err == nil {
		if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
			defer db.Close()
			nCount := 0
			db.QueryRow("select count(*) from employee_info where emp_name = ?", dat["Emp_name"]).Scan(&nCount)
			if nCount <= 0 {
				db.Exec("insert into employee_info(emp_name,emp_pass,emp_position,emp_status,emp_intime) values (?,?,?,?,?)",
					dat["Emp_name"], dat["Emp_pass"], dat["Emp_position"], "在职", time.Now().Unix())
				reply["ErrorCode"] = 0
				reply["Emp_name"] = dat["Emp_name"]
				reply["Emp_pass"] = dat["Emp_pass"]
				reply["Emp_position"] = dat["Emp_position"]
			} else {
				reply["ErrorCode"] = 1
			}
		}
	}
	reply["Cmd"] = "user_add"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 增加账单：post url=http://127.0.0.1/bill_add
{
  cmd: "ui_create_bill",
  mac: "mac1",
  bill_totalmoney: "double",
  bill_returnmoney: "double",
  bill_paymoney: "double",
  bill_returnmoneyremark: "",
  bill_paytype: "nPayType",
  bill_empid: "int",
  bill_empname: "empname",
  bill_remark: "remark",
  bill_state: "int",
  bill_account: "账户",
  telphone: "",
  bill_imagedate:"base64",
  dishes: [
    {
      num: "int",
      bid_disothername: "",
      bid_disprice: "int",
      bid_x1: "int",
      bid_y1: "int",
      bid_x2: "int",
      bid_y2: "int",
      score: "int"
    }
  ]
}
返回：
{
	"Cmd":"ui_create_bill",
	"result":"ok"
}
*/
func bill_add(w http.ResponseWriter, r *http.Request) {
	body, _ := ioutil.ReadAll(r.Body)
	var revData BillInfoStruct
	var pushData MealDataPushListStruct
	if len(r.Header) > 0 {
		for k, v := range r.Header {
			fmt.Printf("%s=%s\n", k, v[0])
		}
	}
	fmt.Println(time.Now().Nanosecond())
	fmt.Println(time.Now().Nanosecond())
	if err := json.Unmarshal(body, &revData); err == nil {
		//1.按规则生成账单号：mac_curTime_billAutoID
		nbill_paytime := time.Now().Unix()
		billAutoID++
		billId := fmt.Sprintf("%s_%d_%d", revData.Mac, nbill_paytime, billAutoID)
		pushData.Order_id = billId
		pushData.Card_id = revData.Bill_account
		pushData.Meal_time = nbill_paytime
		//2.将账单图片以账单号命名保存到 /adytum/billingImage
		newImgPathName := fmt.Sprintf("%s/%s.jpg", RobotBillPath, billId)
		fileImg, _ := os.OpenFile(newImgPathName, os.O_WRONLY|os.O_CREATE, 0666)
		defer fileImg.Close()
		imgdata, _ := base64.StdEncoding.DecodeString(revData.Bill_imagedate)
		fileImg.Write(imgdata)
		//3.将账单信息插入表中
		if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
			defer db.Close()
			if tx, err := db.Begin(); err == nil {
				if stmt, err := tx.Prepare(`insert into bill_info(
											bill_id,bill_empid,bill_empname,
											bill_totalmoney,bill_paymoney,bill_returnmoney,
											bill_returnmoneyremark,bill_paytype,bill_paytime,
											bill_imagepathname,bill_remark,bill_state,bill_account,bill_upload) 
											values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)`); err == nil {
					defer stmt.Close()
					stmt.Exec(billId, revData.Bill_empid, revData.Bill_empname,
						revData.Bill_totalmoney, revData.Bill_paymoney, revData.Bill_returnmoney,
						revData.Bill_returnmoneyremark, revData.Bill_paytype, nbill_paytime,
						fmt.Sprintf("billingImage/%s.jpg", billId), revData.Bill_remark, revData.Bill_state, revData.Bill_account, false)
					//bill_paytype  0初始化;1一卡通;2虚拟卡;3支付宝;4微信;5现金;6挂账;
					if stmtdish, err := tx.Prepare(`insert into bill_dishes(
													bid_billid,bid_disothername,bid_disprice,
													bid_x1,bid_y1,bid_x2,bid_y2,score) 
													values(?,?,?,?,?,?,?,?)`); err == nil {
						defer stmtdish.Close()
						for _, dish := range revData.Dishes {
							if _, err := stmtdish.Exec(billId, dish.Bid_disothername, dish.Bid_disprice,
								dish.Bid_x1, dish.Bid_y1, dish.Bid_x2, dish.Bid_y2, dish.Score); err != nil {
								fmt.Printf("insert into bill_dishes Prepare exec error=%q\n", err)
							}

							pushData.Meal_data = append(pushData.Meal_data, MealDataPushStruct{FoodName: dish.Bid_disothername})
						}
					} else {
						fmt.Printf("insert into bill_dishes Prepare error=%q\n", err)
					}
					//4.如果是挂账，则记录挂账单
					if 6 == revData.Bill_paytype {
						if stmthup, err := tx.Prepare(`insert into credit_info(
													credit_billid,credit_telphone,credit_intime,
													credit_outtime,credit_totalmoney,credit_exist)
													values(?,?,?,?,?,?)`); err == nil {
							defer stmthup.Close()
							if _, err := stmthup.Exec(billId, revData.Telphone, nbill_paytime,
								0, revData.Bill_paymoney, 0); err != nil {
								fmt.Printf("insert into credit_info Prepare exec error=%q\n", err)
							}
						} else {
							fmt.Printf("insert into credit_info Prepare error=%q\n", err)
						}
					}
				}
				tx.Commit()
			}
		}
	} else {
		fmt.Printf("bill_add body json parse err=%q \n", err)
	}

	pushUrlData, _ := json.Marshal(pushData)

	resultmap := make(map[string]interface{})
	resultmap["Cmd"] = "ui_create_bill"
	addBillInfo, _ := json.Marshal(resultmap)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(addBillInfo)

	pushMealDataToURL(pushUrlData)
}

/* 获取账单信息 get url=http://127.0.0.1:10001/bill_query?start=0&end=9999999999999&paytype=0&from=0&count=14
{
  Cmd: "bill_query",
  Count: 7,
  Datas: [
    {
      Bill_paytime: 1565950147,
      Bill_paytype: 6,
      Bill_account: "挂账模拟卡号",
      Bill_paymoney: 90,
      Bill_empname: "admin",
      Bill_id: "mac_1565950147_1",
      Bill_remark: "",
      Telphone: ""
    },
    {
      Bill_paytime: 1565952210,
      Bill_paytype: 6,
      Bill_account: "挂账模拟卡号",
      Bill_paymoney: 150,
      Bill_empname: "admin",
      Bill_id: "mac_1565952210_2",
      Bill_remark: "",
      Telphone: "18910939489"
    }
  ]
}
*/
func bill_query(w http.ResponseWriter, r *http.Request) {
	start := r.FormValue("start")
	end := r.FormValue("end")
	paytype := r.FormValue("paytype")
	from := r.FormValue("from")
	count := r.FormValue("count")
	fmt.Println(start, end, paytype, from, count)
	//paytype  0初始化;1一卡通;2虚拟卡;3支付宝;4微信;5现金;6挂账;
	var billInfo BillQueryInfos
	billInfo.Cmd = "bill_query"
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		nPayType, _ := strconv.Atoi(paytype)
		if 0 == nPayType {
			//查询全部付款类型的流水
			if rows, err := db.Query(`select bill_paytime, bill_paytype, bill_account, bill_paymoney,bill_empname,
				bill_id, bill_remark from bill_info where bill_paytime between ? and ? order by bill_paytime desc limit ? , ? `,
				start, end, from, count); err == nil {
				defer rows.Close()
				for rows.Next() {
					var paytime int64
					var paytype, paymoney int
					var account, empname, id, remark string
					if err := rows.Scan(&paytime, &paytype, &account, &paymoney, &empname, &id, &remark); err == nil {
						telphone := ""
						if 6 == paytype {
							if rowsHanging, err := db.Query("select credit_telphone from credit_info where credit_billid=?", id); err == nil {
								defer rowsHanging.Close()
								for rowsHanging.Next() {
									rowsHanging.Scan(&telphone)
								}
							}
						}
						billInfo.Datas = append(billInfo.Datas, BillQueryInfoStruct{Bill_paytime: paytime, Bill_paytype: paytype,
							Bill_account: account, Bill_paymoney: paymoney, Bill_empname: empname, Bill_id: id, Bill_remark: remark, Telphone: telphone})
					} else {
						fmt.Printf("select * from bill_info rows err2=%q \n", err)
					}
				}
				if err := rows.Err(); err != nil {
					fmt.Printf("select * from bill_info rows err=%q \n", err)
				}
				if rowscount, err := db.Query("select count(*) from bill_info where bill_paytime between ? and ?", start, end); err == nil {
					defer rowscount.Close()
					for rowscount.Next() {
						rowscount.Scan(&billInfo.Count)
					}
				}
			} else {
				fmt.Printf("select * from bill_info err1=%q \n", err)
			}
		} else {
			//根据 付款类型 查询
			if rows, err := db.Query(`select bill_paytime, bill_paytype, bill_account, bill_paymoney,bill_empname,
				bill_id, bill_remark from bill_info where bill_paytype=? and bill_paytime between ? and ? limit ?, ?`,
				nPayType, start, end, from, count); err == nil {
				defer rows.Close()
				for rows.Next() {
					var paytime int64
					var paytype, paymoney int
					var account, empname, id, remark string
					if err := rows.Scan(&paytime, &paytype, &account, &paymoney, &empname, &id, &remark); err == nil {
						telphone := ""
						if 6 == paytype {
							if rowsHanging, err := db.Query("select credit_telphone from credit_info where credit_billid=?", id); err == nil {
								defer rowsHanging.Close()
								for rowsHanging.Next() {
									rowsHanging.Scan(&telphone)
								}
							}
						}
						billInfo.Datas = append(billInfo.Datas, BillQueryInfoStruct{Bill_paytime: paytime, Bill_paytype: paytype,
							Bill_account: account, Bill_paymoney: paymoney, Bill_empname: empname, Bill_id: id, Bill_remark: remark, Telphone: telphone})

					} else {
						fmt.Printf("select * from bill_info rows err2_2=%q \n", err)
					}
				}
				if err := rows.Err(); err != nil {
					fmt.Printf("select * from bill_info rows err_2=%q \n", err)
				}
				if rowscount, err := db.Query("select count(*) from bill_info where bill_paytype=? and bill_paytime between ? and ?", nPayType, start, end); err == nil {
					defer rowscount.Close()
					for rowscount.Next() {
						rowscount.Scan(&billInfo.Count)
					}
				}
			} else {
				fmt.Printf("select * from bill_info err1_2=%q \n", err)
			}
		}
	}

	queryBillInfo, _ := json.Marshal(billInfo)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(queryBillInfo)
}

/* 查询账单统计信息 get url=http://127.0.0.1:10001/bill_countmoney?start=0&end=9999999999999
{
  	Cmd: "bill_countmoney",
	totalCard: 7,
	totalQrcode: 7,
	totalCash: 7,
	totalChargeRoom: 7,
	total: 7,
}
*/
func bill_countmoney(w http.ResponseWriter, r *http.Request) {
	start := r.FormValue("start")
	end := r.FormValue("end")
	resultmap := make(map[string]interface{})
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		totalMoney := 0
		var totalCard, modeCard, totalQrcode, totalQrcode2, totalCash, totalChargeRoom, totalOther int
		//paytype  0初始化;1一卡通;2虚拟卡;3支付宝;4微信;5现金;6挂账;7其他
		db.QueryRow("select sum(bill_paymoney) from bill_info where bill_paytime between ? and ? and bill_paytype=1", start, end).Scan(&totalCard)
		db.QueryRow("select sum(bill_paymoney) from bill_info where bill_paytime between ? and ? and bill_paytype=2", start, end).Scan(&modeCard)
		db.QueryRow("select sum(bill_paymoney) from bill_info where bill_paytime between ? and ? and bill_paytype=3", start, end).Scan(&totalQrcode)
		db.QueryRow("select sum(bill_paymoney) from bill_info where bill_paytime between ? and ? and bill_paytype=4", start, end).Scan(&totalQrcode2)
		db.QueryRow("select sum(bill_paymoney) from bill_info where bill_paytime between ? and ? and bill_paytype=5", start, end).Scan(&totalCash)
		db.QueryRow("select sum(bill_paymoney) from bill_info where bill_paytime between ? and ? and bill_paytype=6", start, end).Scan(&totalChargeRoom)
		db.QueryRow("select sum(bill_paymoney) from bill_info where bill_paytime between ? and ? and bill_paytype=7", start, end).Scan(&totalOther)
		totalMoney = totalCard + modeCard + totalQrcode + totalQrcode2 + totalCash + totalChargeRoom + totalOther

		resultmap["totalCard"] = totalCard
		resultmap["totalQrcode"] = totalQrcode
		resultmap["totalCash"] = totalCash
		resultmap["totalChargeRoom"] = totalChargeRoom
		resultmap["total"] = totalMoney
	}
	resultmap["Cmd"] = "bill_countmoney"
	billCountMoney, _ := json.Marshal(resultmap)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(billCountMoney)
}

/* 查询账单详情根据账单号 get url=http://127.0.0.1:10001/bill_detail?bill_id=mac_1565952210_2
{
  Cmd: "bill_detail",
  Dishes: [
	    {
	      Num: 0,
	      Bid_disothername: "一两米饭",
	      Bid_disprice: 30,
	      Bid_x1: 492,
	      Bid_y1: 126,
	      Bid_x2: 947,
	      Bid_y2: 517,
	      Score: 98
	    }
	]
}
*/
func bill_detail(w http.ResponseWriter, r *http.Request) {
	bill_id := r.FormValue("bill_id")
	var bill_detial BillDetialStruct
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		if rows, err := db.Query(`select bid_disothername,bid_disprice,bid_x1,bid_y1,bid_x2,
				bid_y2, score from bill_dishes where bid_billid=?`, bill_id); err == nil {
			defer rows.Close()
			for rows.Next() {
				var bid_disprice, x1, y1, x2, y2, score int
				var disothername string
				if err := rows.Scan(&disothername, &bid_disprice, &x1, &y1, &x2, &y2, &score); err == nil {
					bill_detial.Dishes = append(bill_detial.Dishes,
						BillDishDetailStruct{Bid_disothername: disothername, Bid_disprice: bid_disprice, Bid_x1: x1, Bid_y1: y1, Bid_x2: x2, Bid_y2: y2, Score: score})
				} else {
					fmt.Printf("select * from bid_disothername rows err=%q \n", err)
				}
			}
		}
	}

	bill_detial.Cmd = "bill_detail"
	bill_detial.BillId = bill_id
	Reply, _ := json.Marshal(bill_detial)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(Reply)
}

// url展示账单图片
// url = http://127.0.0.1:10001/bill_imageShow/mac_1566024477_1.jpg
func bill_imageShow(w http.ResponseWriter, r *http.Request) {
	urlPath := r.URL.Path
	if utf8.RuneCountInString(urlPath) > utf8.RuneCountInString("/bill_imageShow/") {
		_, fileName := filepath.Split(urlPath)
		urlExport := filepath.Join(RobotBillPath, fileName)
		http.ServeFile(w, r, urlExport)
	} else {
		fmt.Println(utf8.RuneCountInString(urlPath))
	}
}

/* 根据手机号模糊搜索未销账的挂账单 url=http://127.0.0.1:10001/bill_chargeSearch?tel=188888888
{
	Cmd:"bill_chargeSearch",
	Datas:[
		{
			Bill_id    string
			Intime     uint32
			TotalMoney int
			Telphone   string
		}
	]
}
*/
func bill_chargeSearch(w http.ResponseWriter, r *http.Request) {
	tel := r.FormValue("tel")
	var reply ChargeInfos
	//
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		if rows, err := db.Query(`select credit_billid,credit_telphone,credit_intime,credit_totalmoney 
		from credit_info where credit_outtime = 0 and credit_telphone like ?`, "%"+tel+"%"); err == nil {
			defer rows.Close()
			for rows.Next() {
				var intime uint32
				var money int
				var id, phone string
				if err := rows.Scan(&id, &phone, &intime, &money); err == nil {
					reply.Datas = append(reply.Datas, ChargeInfo{Bill_id: id, Intime: intime, TotalMoney: money, Telphone: phone})
				} else {
					fmt.Printf("select * from credit_billid rows err2=%q \n", err)
				}
			}

			if err := rows.Err(); err != nil {
				fmt.Printf("select * from credit_billid rows err=%q \n", err)
			}
		} else {
			fmt.Printf("select * from credit_billid err1=%q \n", err)
		}
	}

	reply.Cmd = "bill_chargeSearch"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 根据账单号销账 url=http://127.0.0.1:10001/bill_crossoffAccount
{
	Cmd:"bill_crossoffAccount",
	Datas:["1212","32323"]
}
{
	Cmd:"bill_crossoffAccount"
}
*/
func bill_crossoffAccount(w http.ResponseWriter, r *http.Request) {
	body, _ := ioutil.ReadAll(r.Body)
	type tmpParse struct {
		Cmd   string
		Datas []string
	}
	var revData tmpParse
	if err := json.Unmarshal(body, &revData); err == nil {
		//
		if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
			defer db.Close()
			if tx, err := db.Begin(); err == nil {
				for i := 0; i < len(revData.Datas); i++ {
					tx.Exec("update credit_info set credit_outtime = ? where credit_billid = ?", time.Now().Unix(), revData.Datas[i])
					tx.Exec("update bill_info set bill_remark = ? where bill_id = ?", "已销账", revData.Datas[i])
				}
				tx.Commit()
			}
		}
	}
	reply := make(map[string]interface{})
	reply["Cmd"] = "bill_crossoffAccount"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 用户动作记录及返回需要数据 url=http://127.0.0.1:10001/action_record?start=121212&end=898989898&name=admin
{
	Cmd:"action_record"
	typeplusam:"",
	totalamount:"",
	totalmoney:""
}
*/
func action_record(w http.ResponseWriter, r *http.Request) {
	start := r.FormValue("start")
	end := r.FormValue("end")
	name := r.FormValue("name")
	//
	fmt.Println("action_record", start, end, name)
	//
	reply := make(map[string]interface{})
	//
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		//paytype  0初始化;1一卡通;2虚拟卡;3支付宝;4微信;5现金;6挂账;
		var count1, count2, count3, count4, count5, count6 int
		var money1, money2, money3, money4, money5, money6 int
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 1 and bill_paytime between ? and ?", start, end).Scan(&count1, &money1)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 2 and bill_paytime between ? and ?", start, end).Scan(&count2, &money2)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 3 and bill_paytime between ? and ?", start, end).Scan(&count3, &money3)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 4 and bill_paytime between ? and ?", start, end).Scan(&count4, &money4)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 5 and bill_paytime between ? and ?", start, end).Scan(&count5, &money5)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 6 and bill_paytime between ? and ?", start, end).Scan(&count6, &money6)
		totalamount := count1 + count2 + count3 + count4 + count5 + count6
		totalmoney := money1 + money2 + money3 + money4 + money5 + money6
		//1_amount1_money1,2_amount2_money2...
		typeplusam := fmt.Sprintf("1_%d_%d,2_%d_%d,3_%d_%d,4_%d_%d,5_%d_%d,6_%d_%d",
			count1, money1, count2, money2, count3, money3, count4, money4, count5, money5, count6, money6)
		if _, err := db.Exec(`insert into employee_logs(empname,intime,outtime,totalamount,totalmoney,typeplusam) 
								values(?,?,?,?,?,?)`, name, start, end, totalamount, totalmoney, typeplusam); err == nil {
			reply["typeplusam"] = typeplusam
			reply["totalamount"] = totalamount
			reply["totalmoney"] = totalmoney
		}
	}
	reply["Cmd"] = "action_record"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
	fmt.Println("action_record", reply)
}

func action_switch_user(w http.ResponseWriter, r *http.Request) {
	start := r.FormValue("start")
	end := r.FormValue("end")
	name := r.FormValue("name")
	fmt.Println("action_switch_user", start, end, name)
	reply := make(map[string]interface{})
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		//
		var count1, count2, count3, count4, count5, count6 int
		var money1, money2, money3, money4, money5, money6 int
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 1 and bill_paytime between ? and ?", start, end).Scan(&count1, &money1)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 2 and bill_paytime between ? and ?", start, end).Scan(&count2, &money2)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 3 and bill_paytime between ? and ?", start, end).Scan(&count3, &money3)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 4 and bill_paytime between ? and ?", start, end).Scan(&count4, &money4)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 5 and bill_paytime between ? and ?", start, end).Scan(&count5, &money5)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 6 and bill_paytime between ? and ?", start, end).Scan(&count6, &money6)
		totalamount := count1 + count2 + count3 + count4 + count5 + count6
		totalmoney := money1 + money2 + money3 + money4 + money5 + money6
		//1_amount1_money1,2_amount2_money2...
		typeplusam := fmt.Sprintf("1_%d_%d,2_%d_%d,3_%d_%d,4_%d_%d,5_%d_%d,6_%d_%d",
			count1, money1, count2, money2, count3, money3, count4, money4, count5, money5, count6, money6)
		reply["typeplusam"] = typeplusam
		reply["totalamount"] = totalamount
		reply["totalmoney"] = totalmoney
	}
	reply["Cmd"] = "action_switch_user"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
	fmt.Println("action_switch_user", reply)
}

/* 用户动作记录查询 url=http://127.0.0.1:10001/action_query?start=121212&end=898989898&from=0&count=14
{
	Cmd:"action_query",
	Datas:[
		{
			Name        string
			Intime      uint32
			Outtime     uint32
			Totalamount int
			Totalmoney  int
		}
	]
}
*/
func action_query(w http.ResponseWriter, r *http.Request) {
	start := r.FormValue("start")
	end := r.FormValue("end")
	from := r.FormValue("from")
	count := r.FormValue("count")

	var reply ReportLogs
	reply.Cmd = "action_query"
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()

		if rows, err := db.Query(`select empname,intime,outtime,totalamount,totalmoney 
					from employee_logs where intime between ? and ? limit ?, ?`, start, end, from, count); err == nil {
			defer rows.Close()
			for rows.Next() {
				var intime, outtime uint32
				var totalamount, totalmoney int
				var empname string
				if err := rows.Scan(&empname, &intime, &outtime, &totalamount, &totalmoney); err == nil {
					reply.Datas = append(reply.Datas, ReportLog{Name: empname, Intime: intime, Outtime: outtime, Totalamount: totalamount, Totalmoney: totalmoney})
				} else {
					fmt.Printf("select * from employee_logs rows err2=%q \n", err)
				}
			}
			if err := rows.Err(); err != nil {
				fmt.Printf("select * from employee_logs rows err=%q \n", err)
			}
		} else {
			fmt.Printf("select * from employee_logs err1=%q \n", err)
		}

		db.QueryRow("select count(*) from employee_logs where intime between ? and ?", start, end).Scan(&reply.Count)
	}

	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/*查询日月报表信息 url=http://127.0.0.1:10001/action_record_query?start=121212&end=898989898
{
	Cmd:"action_record_query",
	typeplusam:"",
	totalamount:"",
	totalmoney:""
}
*/
func action_record_query(w http.ResponseWriter, r *http.Request) {
	start := r.FormValue("start")
	end := r.FormValue("end")
	reply := make(map[string]interface{})
	//
	if db, err := sql.Open("sqlite3", RobotDBPath); err == nil {
		defer db.Close()
		//paytype  0初始化;1一卡通;2虚拟卡;3支付宝;4微信;5现金;6挂账;
		var count1, count2, count3, count4, count5, count6 int
		var money1, money2, money3, money4, money5, money6 int
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 1 and bill_paytime between ? and ?", start, end).Scan(&count1, &money1)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 2 and bill_paytime between ? and ?", start, end).Scan(&count2, &money2)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 3 and bill_paytime between ? and ?", start, end).Scan(&count3, &money3)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 4 and bill_paytime between ? and ?", start, end).Scan(&count4, &money4)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 5 and bill_paytime between ? and ?", start, end).Scan(&count5, &money5)
		db.QueryRow("select count(*),sum(bill_paymoney) from bill_info where bill_paytype = 6 and bill_paytime between ? and ?", start, end).Scan(&count6, &money6)
		totalamount := count1 + count2 + count3 + count4 + count5 + count6
		totalmoney := money1 + money2 + money3 + money4 + money5 + money6
		//1_amount1_money1,2_amount2_money2...
		typeplusam := fmt.Sprintf("1_%d_%d,2_%d_%d,3_%d_%d,4_%d_%d,5_%d_%d,6_%d_%d",
			count1, money1, count2, money2, count3, money3, count4, money4, count5, money5, count6, money6)
		reply["typeplusam"] = typeplusam
		reply["totalamount"] = totalamount
		reply["totalmoney"] = totalmoney
	}
	reply["Cmd"] = "action_record_query"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
}

/* 上传报表图片，并返回生成报表的二维码链接 url=http://127.0.0.1:10001/report_imageUpload
{
	Cmd:"report_imageUpload",
	ImageData:"base64",
	MasterIp:"http://127.0.0.1:1001
}
{
	Cmd:"report_imageUpload",
	QrCodeUrl:"http://127.0.0.1:1001/reprotQrCode.png"
}
*/
func report_imageUpload(w http.ResponseWriter, r *http.Request) {
	body, _ := ioutil.ReadAll(r.Body)
	var dat map[string]interface{}
	reply := make(map[string]interface{})
	if err := json.Unmarshal(body, &dat); err == nil {
		NewFilePathName := filepath.Join(CurExeDir, "reprot.jpg")
		fileImg, _ := os.OpenFile(NewFilePathName, os.O_WRONLY|os.O_CREATE, 0666)
		defer fileImg.Close()
		imgdata, _ := base64.StdEncoding.DecodeString(dat["ImageData"].(string))
		fileImg.Write(imgdata)

		qrCode_Url := fmt.Sprintf("%s/report_imageShow/reprotQrCode.png", dat["MasterIp"])
		qrCode_Content := fmt.Sprintf("%s/report_imageShow/reprot.jpg", dat["MasterIp"])
		qrCode_PngFile := filepath.Join(CurExeDir, "reprotQrCode.png")
		if err := qrcode.WriteFile(qrCode_Content, qrcode.Medium, 256, qrCode_PngFile); err == nil {
			reply["QrCodeUrl"] = qrCode_Url
		} else {
			fmt.Println("上传报表图片，并返回生成报表的二维码链接写二维码图片 err=", err)
		}
	}
	reply["Cmd"] = "report_imageUpload"
	replyData, _ := json.Marshal(reply)
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Write(replyData)
	fmt.Println("上传报表图片", reply)
}

/* url展示账单图片
url = http://127.0.0.1:10001/report_imageShow/reprot.jpg
*/
func report_imageShow(w http.ResponseWriter, r *http.Request) {
	urlPath := r.URL.Path
	if utf8.RuneCountInString(urlPath) > utf8.RuneCountInString("/report_imageShow/") {
		_, fileName := filepath.Split(urlPath)
		urlExport := filepath.Join(CurExeDir, fileName)
		http.ServeFile(w, r, urlExport)
	} else {
		fmt.Println(utf8.RuneCountInString(urlPath))
	}
}

/* 对外部 URL 实时推送实际就餐数据
url:读取配置文件的来，配置文件由Robot配置界面设置进去的
*/
func pushMealDataToURL(data []byte) error {
	var otherErr error = nil
	DataUrlFile := filepath.Join(CurExeUpperDir, "EveryMealPushUrl")
	pushMealDataURL, _ := ioutil.ReadFile(DataUrlFile)
	postReq, err := http.NewRequest("POST", string(pushMealDataURL), strings.NewReader(string(data)))
	if err != nil {
		return err
	}
	postReq.Header.Set("Content-Type", "application/json; encoding=utf-8")
	client := &http.Client{}
	resp, err := client.Do(postReq)
	//
	if err != nil {
		return err
	} else {
		defer resp.Body.Close()
		if body, err := ioutil.ReadAll(resp.Body); err != nil {
			return err
		} else {
			var resultjsonmap map[string]interface{}
			if err := json.Unmarshal([]byte(body), &resultjsonmap); err == nil {
				fmt.Println("00=", resultjsonmap)
			}
		}
	}
	return otherErr
}
